package com.lin.views;


import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

import com.lin.utils.MD5;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;

public class SyncImageLoaderForGif {

	Context mActivity;

	private Object lock = new Object();

	private boolean mAllowLoad = true;

	private boolean firstLoad = true;

	private int mStartLoadLimit = 0;

	private int mStopLoadLimit = 0;

	final Handler handler = new Handler();

	byte[] buffer = null;

	private HashMap<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
	private HashMap<String, SoftReference<byte[]>> byteCache = new HashMap<String, SoftReference<byte[]>>();
	public SyncImageLoaderForGif(Context mActivity) {
		super();
		this.mActivity = mActivity;
	}

	public interface OnImageLoadListener {
		public void onImageLoad(Integer t, Drawable drawable, String path,
				byte[] mByte);

		public void onError(Integer t);
	}

	public void setLoadLimit(int startLoadLimit, int stopLoadLimit) {
		if (startLoadLimit > stopLoadLimit) {
			return;
		}
		mStartLoadLimit = startLoadLimit;
		mStopLoadLimit = stopLoadLimit;
	}

	public void restore() {
		mAllowLoad = true;
		firstLoad = true;
	}

	public void lock() {
		mAllowLoad = false;
		firstLoad = false;
	}

	public void unlock() {
		mAllowLoad = true;
		synchronized (lock) {
			lock.notifyAll();
		}
	}

	public void loadImage(Integer t, final String imageUrl,
			OnImageLoadListener listener) {
		final OnImageLoadListener mListener = listener;
		final String mImageUrl = imageUrl;
		final Integer mt = t;

		new Thread(new Runnable() {

			@Override
			public void run() {
				if (!mAllowLoad) {
					synchronized (lock) {
						try {
							lock.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
				try {
					if (byteCache.containsKey(imageUrl)) {
						buffer = byteCache.get(imageUrl).get();
					}else {
						buffer = InputStreamTOByte(new URL(imageUrl).openStream());
						byteCache.put(imageUrl, new SoftReference<byte[]>(buffer));
					}
//					Log.i("tag", "-----------1-------------" + buffer);
				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				if (mAllowLoad && firstLoad) {
					loadImage(mImageUrl, mt, mListener);
				}

				if (mAllowLoad && mt <= mStopLoadLimit && mt >= mStartLoadLimit) {
					loadImage(mImageUrl, mt, mListener);
				}
			}

		}).start();
	}

	private void loadImage(final String mImageUrl, final Integer mt,
			final OnImageLoadListener mListener) {

		if (imageCache.containsKey(mImageUrl)) {
			SoftReference<Drawable> softReference = imageCache.get(mImageUrl);
			final Drawable d = softReference.get();
			if (d != null) {
				handler.post(new Runnable() {
					@Override
					public void run() {
						if (mAllowLoad) {
							File f = new File(SdCardManger.getSaveCachePath(mActivity)
									+ MD5.getMD5().getMd5(mImageUrl));
							mListener.onImageLoad(mt, d, f.getAbsolutePath(),
									buffer);
						}
					}
				});
				return;
			}
		}
		try {

			// if(mImageUrl.contains("gif")) {
			// buffer = loadFromUrl(mImageUrl);
			// } else {

			final Drawable d = loadImageFromUrl(mImageUrl);
			if (d != null) {
				imageCache.put(mImageUrl, new SoftReference<Drawable>(d));
			}
			handler.post(new Runnable() {
				@Override
				public void run() {
					if (mAllowLoad) {
						File f = new File(Environment
								.getExternalStorageDirectory()
								+ "/kapai/cache/"
								+ MD5.getMD5().getMd5(mImageUrl));
						mListener.onImageLoad(mt, d, f.getAbsolutePath(),
								buffer);
					}
				}
			});
			// }
		} catch (Exception e) {
			handler.post(new Runnable() {
				@Override
				public void run() {
					mListener.onError(mt);
				}
			});
			e.printStackTrace();
		}
	}

	/**
	 * 将InputStream转换成byte数组
	 * 
	 * @param in
	 *            InputStream
	 * @return byte[]
	 * @throws IOException
	 */
	private byte[] InputStreamTOByte(InputStream in) throws IOException {

		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		byte[] data = new byte[1024];
		int count = -1;
		while ((count = in.read(data, 0, 1024)) != -1)
			outStream.write(data, 0, count);

		data = null;
		return outStream.toByteArray();
	}

	public Drawable loadImageFromUrl(String url) throws Exception {
		if (Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED)) {
			File f = new File(Environment.getExternalStorageDirectory()
					+ "/kapai/cache/" + MD5.getMD5().getMd5(url));
			if (f.exists()) {
				BitmapFactory.Options option = new BitmapFactory.Options();
				option.inPreferredConfig = Bitmap.Config.RGB_565;
				option.inPurgeable = true;
				option.inInputShareable = true;
				option.inSampleSize = 2;
				FileInputStream mFileInputStream = new FileInputStream(f);
				// buffer = InputStreamTOByte(mFileInputStream);
				Bitmap bitmap = BitmapFactory.decodeStream(mFileInputStream,
						null, option);
				// Log.i("lin", "file exist");
				return new BitmapDrawable(mActivity.getResources(), bitmap); // the
																				// same
																				// thing
			} else {
				new File(Environment.getExternalStorageDirectory()
						+ "/kapai/cache/").mkdirs();
			}
			URL m = new URL(url);
			InputStream i = (InputStream) m.getContent();
			DataInputStream in = new DataInputStream(i);
			FileOutputStream out = new FileOutputStream(f);
			byte[] buffer = new byte[1024];
			int byteread = 0;
			while ((byteread = in.read(buffer)) != -1) {
				out.write(buffer, 0, byteread);
			}
			in.close();
			out.close();
			BitmapFactory.Options option = new BitmapFactory.Options();
			option.inPreferredConfig = Bitmap.Config.RGB_565;
			option.inPurgeable = true;
			option.inInputShareable = true;
			option.inSampleSize = 2;
			FileInputStream mFileInputStream = new FileInputStream(f);
			// this.buffer = InputStreamTOByte(mFileInputStream);
			Bitmap bitmap = BitmapFactory.decodeStream(mFileInputStream, null,
					option);
			return new BitmapDrawable(mActivity.getResources(), bitmap); // the
																			// same
																			// thing
		} else {

			URL m = new URL(url);
			InputStream i = (InputStream) m.getContent();
			// buffer = InputStreamTOByte(i);
			Drawable d = Drawable.createFromStream(i, "src");
			return d;
		}

	}

	byte[] loadFromUrl(String urlstr) throws Exception {
		URL url = new URL(urlstr);
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		connection.setConnectTimeout(10000);
		connection.setReadTimeout(10000);
		connection.setRequestMethod("GET");
		if (connection.getResponseCode() == 200) {
			InputStream is = connection.getInputStream();

			byte[] buffer = getByte(is);
			return buffer;

		} else {
			Log.e("getResponseCode", connection.getResponseCode() + ":");
		}
		return null;
	}

	private final static byte[] getByte(InputStream inputStream) {
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		int len = 0;
		byte[] buffer = new byte[1024];
		try {
			while ((len = inputStream.read(buffer)) > 0) {
				outputStream.write(buffer, 0, len);
			}
			return outputStream.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}
